﻿using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Protocol;
using NationalInstruments.TestStand.Interop.API;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.CompilerServices;

namespace CLVisionMQTT
{
    public class MQTTClient
    {
        #region 变量
        private IMqttClient _mqttClient = null;

        private IMqttClientOptions _mqttOptions;

        public Action<string> EventReceivedMessage;

        // 新增断开连接事件
        public Action<string> EventDisconnected;

        private string _lastReceivedMessage;

        public IMqttClient MqttClient { get => _mqttClient; set => _mqttClient = value; }
        public IMqttClientOptions MqttOptions { get => _mqttOptions; set => _mqttOptions = value; }
        public string LastReceivedMessage { get => _lastReceivedMessage; set => _lastReceivedMessage = value; }

        #endregion

        /// <summary>
        /// 初始化MQTT客户端
        /// </summary>
        public bool IntMqttClient(string server, int port, string username, string password, string topicName, string clientId, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(MQTTClient)}.{nameof(IntMqttClient)}: Start!";
            try
            {
                if (MqttClient != null)
                {
                    DisconnectMqttClient(out ErrorCode, out ErrorText);
                    if (ErrorCode == -1)
                    {
                        return false;
                    }
                }
                var factory = new MqttFactory();
                MqttClient = factory.CreateMqttClient();

                // 这里请根据实际情况修改Broker地址、端口、用户名、密码等
                // server  eg:"broker.hivemq.com", // HiveMQ Cloud 代理地址
                MqttOptions = new MqttClientOptionsBuilder()
                    .WithTcpServer(server, port)
                   .WithCredentials(username, password)
                    .WithCleanSession()
                    .WithClientId(clientId)
                    //.WithTls(new MqttClientOptionsBuilderTlsParameters
                    //{
                    //    UseTls = true, // 如果需要TLS加密，请设置为true
                    //    AllowUntrustedCertificates = true, // 允许不受信任的证书（仅用于测试环境）
                    //    IgnoreCertificateChainErrors = true, // 忽略证书链错误
                    //    IgnoreCertificateRevocationErrors = true // 忽略证书吊销错误
                    //})
                    .Build();

                // 连接
                var result = MqttClient.ConnectAsync(MqttOptions).GetAwaiter().GetResult();

                if (MqttClient.IsConnected)
                {
                    // 订阅一个主题用于接收消息（可根据实际需求修改）
                    MqttClient.UseApplicationMessageReceivedHandler(e =>
                    {
                        string topic = e.ApplicationMessage.Topic;
                        //接收返回的订阅数据
                        LastReceivedMessage = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
                        EventReceivedMessage?.Invoke($"接收{topic}:{LastReceivedMessage}");
                    });
                    // 订阅主题  eg: "test/topic"
                    MqttClient.SubscribeAsync(topicName).GetAwaiter().GetResult();

                    // 注册断开连接事件
                    MqttClient.UseDisconnectedHandler(e =>
                    {
                        EventDisconnected?.Invoke("客户端与服务器断开连接！");
                    });
                }
                else
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(MQTTClient)}.{nameof(IntMqttClient)}: Fail! Unable to connect.";
                    return false;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(MQTTClient)}.{nameof(IntMqttClient)}: Fail! " + ex.Message;
                return false;
            }

            ErrorCode = 0;
            ErrorText = $"{nameof(MQTTClient)}.{nameof(IntMqttClient)}: End!";
            return true;
        }

        /// <summary>
        /// 发送数据到MQTT
        /// </summary>
        public bool PublishData(string topicName, string data, MqttQualityOfServiceLevel mqttQualityOfServiceLevel, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(MQTTClient)}.{nameof(PublishData)}: Start!";

            try
            {
                if (MqttClient == null || !MqttClient.IsConnected)
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(MQTTClient)}.{nameof(PublishData)}: Fail! 未初始化MQTTCallerTS对象，检查IntMqttClient方法是否调用并执行成功！";
                    return false;
                }

                var message = new MqttApplicationMessageBuilder()
                    .WithTopic(topicName)
                    .WithPayload(data)
                    .WithQualityOfServiceLevel(mqttQualityOfServiceLevel)
                    .WithRetainFlag(false)
                    .Build();

                MqttClient.PublishAsync(message).GetAwaiter().GetResult();
                ErrorCode = 0;
                ErrorText = $"{nameof(MQTTClient)}.{nameof(PublishData)}: End!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(MQTTClient)}.{nameof(PublishData)}: Fail! " + ex.Message;
                return false;
            }
        }



        public bool SubscribeTopic(out int ErrorCode, out string ErrorText, params string[] topicNames)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(MQTTClient)}.{nameof(SubscribeTopic)}: Start!";
            try
            {
                if (MqttClient == null || !MqttClient.IsConnected)
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(MQTTClient)}.{nameof(SubscribeTopic)}: Fail! 未初始化MQTTCallerTS对象，检查IntMqttClient方法是否调用并执行成功！";
                    return false;
                }
                List<MqttTopicFilter> topicFilters = new List<MqttTopicFilter>();
                for (int i = 0; i < topicNames.Length; i++)
                {
                    MqttTopicFilter mqttTopicFilter = new MqttTopicFilter();
                    mqttTopicFilter.Topic = topicNames[i];
                    mqttTopicFilter.QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce;
                    topicFilters.Add(mqttTopicFilter);
                }
                MqttClient.SubscribeAsync(topicFilters.ToArray()).GetAwaiter().GetResult();
                ErrorCode = 0;
                ErrorText = $"{nameof(MQTTClient)}.{nameof(SubscribeTopic)}: End!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(MQTTClient)}.{nameof(SubscribeTopic)}: Fail! " + ex.Message;
                return false;
            }
        }
        public bool UnsubscribeTopic(out int ErrorCode, out string ErrorText, params string[] topicNames)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(MQTTClient)}.{nameof(UnsubscribeTopic)}: Start!";
            try
            {
                if (MqttClient == null || !MqttClient.IsConnected)
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(MQTTClient)}.{nameof(UnsubscribeTopic)}: Fail! 未初始化MQTTCallerTS对象，检查IntMqttClient方法是否调用并执行成功！";
                    return false;
                }
                MqttClient.UnsubscribeAsync(topicNames).GetAwaiter().GetResult();
                ErrorCode = 0;
                ErrorText = $"{nameof(MQTTClient)}.{nameof(UnsubscribeTopic)}: End!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(MQTTClient)}.{nameof(UnsubscribeTopic)}: Fail! " + ex.Message;
                return false;
            }
        }

        /// <summary>
        /// MQTT客户端断开连接
        /// </summary>
        public bool DisconnectMqttClient(out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(MQTTClient)}.{nameof(DisconnectMqttClient)}: Start!";

            try
            {
                if (MqttClient == null)
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(MQTTClient)}.{nameof(DisconnectMqttClient)}: Fail! 断开连接失败！未初始化客户端，检查IntMqttClient方法是否调用并执行成功！";
                    return false;
                }

                if (!MqttClient.IsConnected)
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(MQTTClient)}.{nameof(DisconnectMqttClient)}: Fail! 断开连接失败！客户端未连接！";
                    return false;
                }

                MqttClient.DisconnectAsync().GetAwaiter().GetResult();
                MqttClient?.Dispose();
                MqttClient = null;
                MqttOptions = null;
                ErrorCode = 0;
                ErrorText = $"{nameof(MQTTClient)}.{nameof(DisconnectMqttClient)}: End!";
                return true;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(MQTTClient)}.{nameof(DisconnectMqttClient)}: Fail! " + ex.Message;
                return false;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="receivedMessage"></param>
        /// <param name="ErrorCode"></param>
        /// <param name="ErrorText"></param>
        /// <param name="timeoutMs">超时时间（毫秒），默认 3000ms</param>
        /// <param name="pollIntervalMs">轮询间隔（毫秒），默认 50ms</param>
        /// <returns></returns>
        public bool ReceiveDataWithTimeout(out string receivedMessage, out int ErrorCode, out string ErrorText, int timeoutMs = 3000, int pollIntervalMs = 50)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(MQTTClient)}.{nameof(ReceiveDataWithTimeout)}: Start!";
            receivedMessage = string.Empty;

            try
            {
                if (MqttClient == null || !MqttClient.IsConnected)
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(MQTTClient)}.{nameof(ReceiveDataWithTimeout)}: Fail! Client not connected.";
                    return false;
                }

                int waited = 0;
                while (waited < timeoutMs)
                {
                    if (!string.IsNullOrEmpty(LastReceivedMessage))
                    {
                        receivedMessage = LastReceivedMessage;
                        LastReceivedMessage = null; // 读取后清空
                        ErrorText = $"{nameof(MQTTClient)}.{nameof(ReceiveDataWithTimeout)}: End!";
                        return true;
                    }
                    System.Threading.Thread.Sleep(pollIntervalMs);
                    waited += pollIntervalMs;
                }

                // 超时未收到新消息
                ErrorCode = -1;
                ErrorText = $"{nameof(MQTTClient)}.{nameof(ReceiveDataWithTimeout)}: Fail! Timeout, no new message received.";
                return false;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(MQTTClient)}.{nameof(ReceiveDataWithTimeout)}: Fail! " + ex.Message;
                return false;
            }
        }
        ///// <summary>
        ///// 接收MQTT数据（返回最近一次收到的消息）
        ///// </summary>
        //public bool ReceiveData(out string receivedMessage, out int ErrorCode, out string ErrorText)
        //{
        //    ErrorCode = 0;
        //    ErrorText = $"{nameof(MQTTClient)}.{nameof(ReceiveData)}: Start!";
        //    receivedMessage = string.Empty;

        //    try
        //    {
        //        if (_mqttClient == null || !_mqttClient.IsConnected)
        //        {
        //            ErrorCode = -1;
        //            ErrorText = $"{nameof(MQTTClient)}.{nameof(ReceiveData)}: Fail! Client not connected.";
        //            return false;
        //        }
        //        if (!string.IsNullOrEmpty(lastReceivedMessage))
        //        {
        //            receivedMessage = lastReceivedMessage;
        //            lastReceivedMessage = null; // 读取后清空
        //        }
        //        return true;
        //    }
        //    catch (Exception ex)
        //    {
        //        ErrorCode = -1;
        //        ErrorText = $"{nameof(MQTTClient)}.{nameof(ReceiveData)}: Fail! " + ex.Message;
        //        return false;
        //    }
        //}
        private enum JValueType
        {
            Integer,
            Float,
            String,
            Boolean
        }

        private static bool IsJOjbect(string value)
        {
            try
            {
                JObject ja = JObject.Parse(value);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }




    }
}
